import uuid
import io
import asyncio
from datetime import datetime
from minio import Minio
from minio.error import S3Error
from models.file import File
from utils.result_util import ok, error

# MinIO配置信息
MINIO_ENDPOINT = '39.106.49.21'
MINIO_PORT = 9090
MINIO_ACCESS_KEY = 'minio'
MINIO_SECRET_KEY = 'minio@mini_game'
MINIO_BUCKET = 'minigameoss'
MINIO_SECURE = False  # 根据实际情况设置是否使用HTTPS

# 初始化MinIO客户端 - 使用HTTP API方式
minio_client = None
try:
    # 使用原始的MinIO客户端初始化方式
    minio_client = Minio(
        f"{MINIO_ENDPOINT}:{MINIO_PORT}",  # 合并endpoint和port
        access_key=MINIO_ACCESS_KEY,
        secret_key=MINIO_SECRET_KEY,
        secure=MINIO_SECURE,
        region='us-east-1'  # 添加region参数
    )
    
    print(f"MinIO客户端初始化成功，配置: endpoint={MINIO_ENDPOINT}:{MINIO_PORT}, secure={MINIO_SECURE}")
except S3Error as e:
    print(f"MinIO客户端初始化失败 (S3Error): {e}")
    minio_client = None
except Exception as e:
    print(f"MinIO客户端初始化异常 (Exception): {e}")
    minio_client = None


async def upload_file(file_data, filename):
    """上传文件到MinIO并记录到数据库"""
    if not minio_client:
        return error(message="MinIO客户端未初始化，文件上传失败")
        
    try:
        # 生成存储文件名
        stored_filename = str(uuid.uuid4())
        
        # 异步上传文件到MinIO
        loop = asyncio.get_event_loop()
        await loop.run_in_executor(
            None,
            lambda: minio_client.put_object(
                MINIO_BUCKET,
                stored_filename,
                io.BytesIO(file_data),  # 使用BytesIO包装bytes对象
                len(file_data),
                content_type='application/octet-stream'  # 设置内容类型
            )
        )
        
        # 计算文件大小
        file_size = len(file_data)
        
        # 记录到数据库
        file_record = await File.create(
            filename=filename,
            stored_filename=stored_filename,
            file_path=stored_filename,  # 存储为MinIO中的对象名称
            file_size=file_size,
            upload_time=datetime.now(),
            is_deleted=False,
            download_count=0
        )
        
        return ok({
            'file_id': file_record.id,
            'filename': filename,
            'stored_filename': stored_filename,
            'file_size': file_size
        })
    except S3Error as e:
        print(f"MinIO文件上传失败: 错误代码={e.code}, 消息={e.message}")
        return error(message=f"文件上传失败: {str(e)}")
    except Exception as e:
        print(f"文件上传过程中出现错误: {e}")
        return error(message=f"文件上传失败: {str(e)}")


async def get_file_by_filename(stored_filename):
    """根据存储文件名从MinIO获取文件"""
    if not minio_client:
        return error(message="MinIO客户端未初始化，文件获取失败")
        
    try:
        # 查询数据库获取文件信息
        file_record = await File.get_or_none(
            stored_filename=stored_filename,
            is_deleted=False
        )
        
        if not file_record:
            return error(message="文件不存在或已删除")
        
        # 异步从MinIO获取文件
        loop = asyncio.get_event_loop()
        data = await loop.run_in_executor(
            None,
            lambda: minio_client.get_object(
                MINIO_BUCKET,
                stored_filename
            )
        )
        
        # 读取文件数据
        file_data = data.read()
        data.close()
        
        # 更新下载次数
        file_record.download_count += 1
        await file_record.save()
        
        return ok({
            'file_data': file_data,
            'filename': file_record.filename,
            'file_size': file_record.file_size
        })
    except S3Error as e:
        print(f"MinIO文件获取失败: {e}")
        return error(message=f"文件获取失败: {str(e)}")
    except Exception as e:
        print(f"文件获取过程中出现错误: {e}")
        return error(message=f"文件获取失败: {str(e)}")


async def delete_file_by_filename(stored_filename):
    """根据存储文件名从MinIO删除文件并更新数据库状态"""
    if not minio_client:
        return error(message="MinIO客户端未初始化，文件删除失败")
        
    try:
        # 查询数据库获取文件信息
        file_record = await File.get_or_none(
            stored_filename=stored_filename,
            is_deleted=False
        )
        
        if not file_record:
            return error(message="文件不存在或已删除")
        
        # 异步从MinIO删除文件
        loop = asyncio.get_event_loop()
        await loop.run_in_executor(
            None,
            lambda: minio_client.remove_object(
                MINIO_BUCKET,
                stored_filename
            )
        )
        
        # 更新数据库状态
        file_record.is_deleted = True
        await file_record.save()
        
        return ok({"message": "文件删除成功"})
    except S3Error as e:
        print(f"MinIO文件删除失败: {e}")
        return error(message=f"文件删除失败: {str(e)}")
    except Exception as e:
        print(f"文件删除过程中出现错误: {e}")
        return error(message=f"文件删除失败: {str(e)}")